package com.gzsxy.sso.core.config;


import com.gzsxy.sso.common.result.ResultCodeEnum;
import com.gzsxy.sso.common.utils.RequestUtil;
import com.gzsxy.sso.core.entity.Role;
import com.gzsxy.sso.core.entity.User;
import com.gzsxy.sso.core.model.CustomUser;
import com.gzsxy.sso.core.service.RoleService;
import com.gzsxy.sso.core.service.UserRoleService;
import com.gzsxy.sso.core.service.UserService;
import com.gzsxy.sso.resources.cons.HttpStatus;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;


/**
 * @author xiaolong
 * @version 1.0
 * @description: springSecurity用户认证
 * @date 2021/11/2 20:46
 */
@Component
@Slf4j
public class MemberDetailsService implements UserDetailsService {

    @Autowired
    private UserService userService;


    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private HttpServletRequest request;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //1.登录的时候，调用该方法userName 查询账户是否存在，在验证账户的密码
        User user = userService.findByUsername(username);

        if(user == null){
            throw new BadCredentialsException(ResultCodeEnum.LOGIN_USER_PASSWORD_ERROR.getMessage());
        } else if (user.getFreeze()){
            throw new BadCredentialsException(ResultCodeEnum.LOGIN_DISABLED_ERROR.getMessage());

        }
        //2.在根据该账户的userid 查询该用户对应的权限
//        List<Permission> permissionList = userService.findPermissionByUsername(username);
//        //绑定权限
//        ArrayList<GrantedAuthority> grantedAuthorities = new ArrayList<>();
//        permissionList.forEach((a) ->{
//            grantedAuthorities.add(new SimpleGrantedAuthority(a.getPermTag()));
//        });

        //绑定角色权限
        List<Role> roleList = userRoleService.findRolesByUserId(user.getId());
        //获取用户角色
        List<GrantedAuthority> grantedAuthorities = getAuthorities(roleList);


        log.info(">>roleList:{}<<",roleList);
        //设置权限
        String authPassword = new BCryptPasswordEncoder().encode(user.getPassword());

        //****一定要把权限存入进去，不然用户通过认证但没有权限，就算是下面通过父类去赋值了grantedAuthorities权限，
        // 但是最后返回的customUser是没有权限grantedAuthorities，然后把之前父类的覆盖掉了*****
        user.setAuthorities(grantedAuthorities);
        //创建 security用户权限模型
        CustomUser customUser = new CustomUser(username,authPassword,grantedAuthorities);
        customUser.setIsAdmin(false);
        customUser.setIsSadmin(false);
        //获取客户端的ip
        customUser.setClientIp(RequestUtil.getClientIp(request));

        //角色代码列表
        List<String> roleCodes = new ArrayList<>();
        List<String> roleIds = new ArrayList<>();
        for (Role role : roleList) {
            String code = role.getCode();
            String roleId = role.getId();
            roleCodes.add(code);
            roleIds.add(roleId);

            if (role.getIsAdmin()){
                customUser.setIsAdmin(true);
            }
            if (role.getIsSadmin()){
                customUser.setIsSadmin(true);
            }
        }
        //角色代码列表转为字符串存储
        customUser.setRoleCodes(com.gzsxy.sso.common.utils.StringUtils.listToString(roleCodes));
        //角色id转为字符串存储
        customUser.setRoleIds(com.gzsxy.sso.common.utils.StringUtils.listToString(roleIds));
        customUser.setCode(HttpStatus.OK.getCode());
        customUser.setMsg(HttpStatus.OK.getReasonCN());
        //将tUser里面的属性值复制到customUser
        BeanUtils.copyProperties(user,customUser);

        return customUser;
    }


    /**
     * @description: 获取用户的角色权限
     * @param roleList 角色列表
     * @return
     */
    private List<GrantedAuthority> getAuthorities(List<Role> roleList){
        //绑定角色权限
        ArrayList<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        for (Role role : roleList) {
            String code = role.getCode();
            if (StringUtils.isNotEmpty(code)){
                //ROLE_固定格式
                grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_"+code));
            }
        }
        return grantedAuthorities;
    }
}
